﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SC
{
    public class SocketServer
    {
        #region socket
        //用于通信的Socket
        Socket socket;
        //用于监听的SOCKET
        Socket socketWatch;
        //将远程连接的客户端的IP地址和Socket存入集合中
        public Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
        //创建监听连接的线程
        Thread AcceptSocketThread;
        //接收客户端发送消息的线程
        Thread threadReceive;

        public bool ForceAbort = false;

        public delegate void ClientConnectedEvent(string ip);
        public ClientConnectedEvent clientConnectedEvent;

        public delegate void RecvEvent(Socket socketSend);
        public RecvEvent recvEvent;

        public delegate void ClientForceDisconnect(string ipkey);
        public ClientForceDisconnect clientForceDisconnect;

        /// <summary>
        /// 连接失败事件
        /// </summary>
        public Action<String> connectError;

        public SocketServer(string ip,int port)
        {
            dicSocket = new Dictionary<string, Socket>();

            Start(ip, port);
        }

        /// <summary>
        /// 等待客户端的连接，并且创建与之通信用的Socket
        /// </summary>
        /// <param name="obj"></param>
        private void StartListen(object obj)
        {
            Socket socketWatch = obj as Socket;
            while (!ForceAbort)
            {
                try
                {
                    if (ForceAbort)
                    {
                        break;
                    }
                    //等待客户端的连接，并且创建一个用于通信的Socket
                    socket = socketWatch.Accept();
                    //Debug.Log("客户端接入");
                    //获取远程主机的ip地址和端口号
                    string strIp = socket.RemoteEndPoint.ToString();



                    if (!dicSocket.ContainsKey(strIp))
                    {
                        dicSocket.Add(strIp, socket);
                        if (clientConnectedEvent != null)
                        {
                            clientConnectedEvent(strIp);
                        }
                        //Debug.Log("SocketServer 客户端连接成功 开启接收线程");
                        //定义接收客户端消息的线程
                        Thread threadReceive = new Thread(new ParameterizedThreadStart(Receive));
                        threadReceive.IsBackground = true;
                        threadReceive.Start(socket);
                    }
                    else
                    {
                        //Debug.Log("IP 已存在");
                    }
                }
                catch (Exception ex)
                {
                    //Debug.Log("SocketServer监听错误:"+ex.Message);
                    throw ex;
                }


            }
        }


        /// <summary>
        /// 服务器端不停的接收客户端发送的消息
        /// </summary>
        /// <param name="obj"></param>
        private void Receive(object obj)
        {
            try
            {
                Socket socket = obj as Socket;

                while (!ForceAbort)
                {
                    if (!socket.Connected || ForceAbort)
                    {
                        break;
                    }
                    if (recvEvent != null)
                    {
                        recvEvent(socket);
                    }
                }
            }
            catch (SocketException ex)
            {
                if (clientForceDisconnect != null && socket != null)
                {
                    clientForceDisconnect(socket.RemoteEndPoint.ToString());
                }
                if (connectError != null)
                {
                    connectError(ex.Message);
                }
            }
        }


        private void Start(string ip, int port)
        {
            //开启socket服务
            try
            {
                if (socketWatch == null)
                {
                    //当点击开始监听的时候 在服务器端创建一个负责监听IP地址和端口号的Socket
                    socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                }

                //获取ip地址
                IPAddress iPAddress = IPAddress.Parse(ip);

                //创建端口号
                IPEndPoint point = new IPEndPoint(iPAddress, port);

                if (!socketWatch.IsBound)
                {
                    socketWatch.Bind(point);
                }

                //开始监听:设置最大可以同时连接多少个请求
                socketWatch.Listen(1000);

                //创建线程
                AcceptSocketThread = new Thread(new ParameterizedThreadStart(StartListen));
                AcceptSocketThread.IsBackground = true;
                AcceptSocketThread.Start(socketWatch);
            }
            catch (Exception ex)
            {
                //Common.Log.Error(ex.Message+"请检查配置文件 common.ini");

                //Application.Exit();
                throw ex;
            }
        }

        public void CloseClient(string clientkey)
        {
            if (dicSocket.ContainsKey(clientkey))
            {
                dicSocket[clientkey].Disconnect(false);
                dicSocket[clientkey].Close();
                //Common.Log.Info(clientkey+"正常关闭");
            }
        }

        /// <summary>
        /// 发送消息给客户端
        /// </summary>
        /// <param name="messageType"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        public int Send(string clientkey, byte[] buffer)
        {
            int count = 0;
            if (dicSocket != null && dicSocket[clientkey] != null)
            {
                Socket socket = dicSocket[clientkey];
                if (dicSocket[clientkey] != null && socket.Connected)
                {
                    try
                    {
                        count = socket.Send(buffer);
                    }
                    catch (Exception ex)
                    {
                        //Common.Log.Info("发型消息出错:",e);
                        dicSocket.Remove(clientkey);
                        throw ex;
                    }
                }
            }
            return count;
        }

        public int SendStream(string clientkey, byte[] buffer)
        {
            int count = 0;
            if (dicSocket != null && dicSocket[clientkey] != null)
            {
                Socket socket = dicSocket[clientkey];
                if (dicSocket[clientkey] != null && socket.Connected)
                {
                    try
                    {
                        count = socket.Send(buffer);
                    }
                    catch (Exception ex)
                    {
                        //Common.Log.Info("发型消息出错:",e);
                        throw ex;
                    }
                }
            }

            return count;
        }

        public void Close()
        {
            ForceAbort = true;
            if (socketWatch != null)
            {
                socketWatch.Close();
                socketWatch = null;
            }
            if (socket != null)
            {
                socket.Close();
                socket = null;
            }
            //终止线程
            if (AcceptSocketThread != null)
            {
                AcceptSocketThread.Abort();
                AcceptSocketThread = null;
            }
            if (threadReceive != null)
            {
                threadReceive.Abort();
                threadReceive = null;
            }
        }
        #endregion
    }
}
